package mkv.MyGUI;
import processing.core.*;

public class MyGUIPinSlider extends MyGUIObject {
  // Contraints
  private int reactionWidth, reactionHeight;
  // Values
  private int minValue, maxValue;
  public int value = 0;
  
  /* Constructors */
  public MyGUIPinSlider(PApplet root, int x, int y, int width, int height, int minValue, int maxValue) {
    super(root, x, y);
    this._width = width;
    this._height = height;
    this.minValue = minValue;
    this.maxValue = maxValue;
    // GUI testing showed that max/min boundaries should be inside marked heights,
    // because it gets really fiddly to set the min/max values if your mouse is near
    // the boundaries of an object, or the edge of the screen.
    reactionHeight = _height;
    reactionWidth = _width;
  }
  
  /* Setter methods */
  // Set initial value
  public void setValue(int newValue) {
    value = value = PApplet.constrain(newValue, minValue, maxValue);
  }
  
  /* Get methods */
  // Return slider position/value
  public int getValue()  {
    return value;
  }
  
  /* Internal methods */
  // This method updates the slider based on mouse position. However
  // it should only be called if the mouse is within the object's boundaries
  private void updateValue() {
    // Update local mouse values
    updateLocalMouse();
    // Only to be called if mouse is within boundaries
    int target = tmouseX + _width/2;
    value = (int)((float)target/(float)reactionWidth * (maxValue-minValue)) + minValue;
    value = PApplet.constrain(value, minValue, maxValue);
  }
  
  public void mousePressed() {
    if(hasFocus()) {
      dragged = true;
      hover = true;
      updateValue();
    }
  }

  public void mouseReleased() {
    // If mouse was previous dragged (boolean dragged) from this object,
    // and the mouse was released then create an event to signal this value has been updated
    if(dragged) {
      MyGUIActionEvent a = new MyGUIActionEvent(this, _actionCommand);
      a.sendEvent(_root);
      updateValue();
    }
    // Object no longer dragged
    dragged = false;
  } 
  
  public void mouseDragged() {
    if(dragged) {
      updateValue();
    }  
  }
  
  // Moved main draw code to sub method drawStates() to easily encapsulate
  public void draw() {
    if(_visible) drawStates();
  }
  
  public void drawStates() {
   // alias to shorten _style property to st
    MyGUIStyle st;
    if(_style == null) {
      st = _parent.getStyle();
    } else {
      st = _style;
    }
    if(_width%2 == 1) _width++; // hack so that centrally drawn lines are always in the same place
    if(_height%2 == 1) _height++; // hack so that centrally drawn lines are always in the same place
    // set regularly used vars:
    final int halfw = PApplet.round((float)_width/2 + st.padding);
    final int halfh = PApplet.round((float)_height/2 + st.padding);
    final int qurtw = PApplet.round((float)_width/4 + st.padding);
    final int qurth = PApplet.round((float)_height/4 + st.padding);
    final int sliderPos = PApplet.round((float)(value-minValue)/(float)(maxValue-minValue)*_width)-halfw;
    // decide on draw state
    hover = checkForHit();
    // move draw object to coordinates
    _root.pushMatrix();
    _root.translate(_x, _y);
    _root.scale(_scale);
    _root.rotate(PApplet.radians(_rotation));
    // Set default properties
    _root.rectMode(PApplet.CORNERS);
    _root.strokeWeight(st.strokeWeight);
    // Draw pegs, constant for all
    _root.stroke(st.shadow);
    int wseg = _width/10;
    for(int p=0; p<11; p++) {
      _root.line(-_width/2+wseg*p, qurth, -_width/2+wseg*p, halfh);
    }
    // Draw different states
    if(isDisabled()) {
      _root.stroke(st.shadow);
      _root.fill(st.disabled);
      _root.rect(-halfw, -qurth/2, halfw, qurth/2);
      _root.stroke(st.shadow);
      _root.translate(sliderPos, 0);
      _root.beginShape(PApplet.POLYGON); // Note you read correct, all coords based off heights not width.
        _root.vertex(-qurth, -halfh); _root.vertex(-qurth, qurth); _root.vertex(0, halfh); _root.vertex(qurth, qurth); _root.vertex(qurth, -halfh);
      _root.endShape(); 
    }
    else if(dragged) {
      // drag/depressed state
      _root.stroke(st.shadow);
      _root.fill(st.face);
      _root.rect(-halfw, -qurth/2, halfw, qurth/2);
      _root.stroke(st.shadow);
      _root.translate(sliderPos, 0);
      _root.beginShape(PApplet.POLYGON); // Note you read correct, all coords based off heights not width.
        _root.vertex(-qurth, -halfh); _root.vertex(-qurth, qurth); _root.vertex(0, halfh); _root.vertex(qurth, qurth); _root.vertex(qurth, -halfh);
      _root.endShape(); 
      _root.stroke(st.shadow);
      _root.beginShape(PApplet.POLYGON); // Note you read correct, all coords based off heights not width.
        _root.vertex(-qurth+1, -halfh+1); _root.vertex(-qurth+1, qurth); _root.vertex(0, halfh-1); _root.vertex(qurth-1, qurth); _root.vertex(qurth-1, -halfh+1);
      _root.endShape(); 
    } 
    else if(hover) {
      // hover state
      _root.stroke(st.shadow);
      _root.fill(st.face);
      _root.rect(-halfw, -qurth/2, halfw, qurth/2);
      _root.stroke(st.shadow);
      _root.translate(sliderPos, 0);
      if(hasFocus()) {
        // focus and hover state
        _root.fill(st.highlight);
        _root.beginShape(PApplet.POLYGON); // Note you read correct, all coords based off heights not width.
          _root.vertex(-qurth, -halfh); _root.vertex(-qurth, qurth); _root.vertex(0, halfh); _root.vertex(qurth, qurth); _root.vertex(qurth, -halfh);
        _root.endShape(); 
      } else {
        _root.beginShape(PApplet.POLYGON); // Note you read correct, all coords based off heights not width.
          _root.vertex(-qurth, -halfh); _root.vertex(-qurth, qurth); _root.vertex(0, halfh); _root.vertex(qurth, qurth); _root.vertex(qurth, -halfh);
        _root.endShape(); 
        _root.stroke(st.highlight);
        _root.beginShape(PApplet.POLYGON); // Note you read correct, all coords based off heights not width.
          _root.vertex(-qurth+1, -halfh+1); _root.vertex(-qurth+1, qurth); _root.vertex(0, halfh-1); _root.vertex(qurth-1, qurth); _root.vertex(qurth-1, -halfh+1);
        _root.endShape(); 
      }
    } 
    else if(hasFocus()) {
      // focused default state
      _root.stroke(st.shadow);
      _root.fill(st.face);
      _root.rect(-halfw, -qurth/2, halfw, qurth/2);
      _root.translate(sliderPos, 0);
      _root.stroke(st.shadow);
      _root.beginShape(PApplet.POLYGON); // Note you read correct, all coords based off heights not width.
        _root.vertex(-qurth, -halfh); _root.vertex(-qurth, qurth); _root.vertex(0, halfh); _root.vertex(qurth, qurth); _root.vertex(qurth, -halfh);
      _root.endShape(); 
      _root.stroke(st.highlight);
      _root.beginShape(PApplet.POLYGON); // Note you read correct, all coords based off heights not width.
        _root.vertex(-qurth+1, -halfh+1); _root.vertex(-qurth+1, qurth); _root.vertex(0, halfh-1); _root.vertex(qurth-1, qurth); _root.vertex(qurth-1, -halfh+1);
      _root.endShape(); 
    } 
    else {
      // default state
      _root.stroke(st.shadow);
      _root.fill(st.face);
      _root.rect(-halfw, -qurth/2, halfw, qurth/2);
      _root.translate(sliderPos, 0);
      _root.beginShape(PApplet.POLYGON); // Note you read correct, all coords based off heights not width.
        _root.vertex(-qurth, -halfh); _root.vertex(-qurth, qurth); _root.vertex(0, halfh); _root.vertex(qurth, qurth); _root.vertex(qurth, -halfh);
      _root.endShape(); 
    }
    _root.popMatrix();
  }

}
